home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Washington_1988 / DevCon88.1 / Assembler / blitter / draw.asm < prev   
Encoding:
Assembly Source File  |  1992-08-27  |  7.8 KB  |  225 lines

  1. ;
  2. ; Copyright (c) 1988 Commodore-Amiga, Inc.
  3. ;
  4. ; Executables based on this information may be used in software
  5. ; for Commodore Amiga computers.  All other rights reserved.
  6. ;
  7. ; This information is provided "as is"; no warranties are made.
  8. ; All use is at your own risk, and no liability or responsibility is assumed.
  9. ;
  10.          CODE
  11.         NOLIST
  12.         INCLUDE    "exec/types.i"
  13.         INCLUDE    "graphics/rastport.i"
  14.         INCLUDE    "custom.i"
  15.         INCLUDE    "globals.i"
  16.         LIST
  17.  
  18.         XREF    _LVOOwnBlitter,_LVODisownBlitter
  19.  
  20.         XDEF    Draw,Line,Clear
  21.  
  22.  
  23. ;============================================================================
  24. ; Draw( rp,x2,y2 )
  25. ;       a0 d0 d1
  26. ;
  27. ; Same as line but calls OwnBlitter before calling the line drawing routine.
  28. ;============================================================================
  29. Draw        move.l    a6,-(sp)
  30.         movea.l    GfxLib(a5),a6        need to own the blitter
  31.         movem.l    d0/d1/a0,-(sp)        save line arguments
  32.         jsr    _LVOOwnBlitter(a6)    get the blitter
  33.         movem.l    (sp)+,d0/d1/a0        restore line args
  34.         bsr.s    Line            draw the line
  35.         jsr    _LVODisownBlitter(a6)    give blitter back to system
  36.         movea.l    (sp)+,a6
  37.         rts
  38.         
  39. ;============================================================================
  40. ; NAME
  41. ;    Line ( rp,x2,y2 )
  42. ;        a0 d0 d1
  43. ;
  44. ; Draws a line from the current position to x2,y2 in the given RastPort.
  45. ; Current color, linepat, mask and flags are observed from the rastport info.
  46. ; The blitter must be owned before calling this routine to draw lines.
  47. ;============================================================================
  48. Line        movem.l    d2-d6/a2-a3,-(sp)
  49.         movea.l    rp_BitMap(a0),a1    point to the bitmap struct
  50.         movea.l    #_custom,a3        point to custom chips
  51.         move.w    d0,d2            get start and end points
  52.         move.w    d1,d3
  53.         movem.w    rp_cp_x(a0),d0/d1    start positions
  54.         movem.w    d2/d3,rp_cp_x(a0)    save new start position
  55.  
  56.         moveq.l    #$0f,d4            compute ASH3-ASH0
  57.         and.w    d0,d4            for preshifting bltadat
  58.         sub.w    d0,d2            convert X2 to deltaX
  59.         sub.w    d1,d3            convert Y2 to deltaY
  60.         mulu.w    bm_BytesPerRow(a1),d1    offset to correct bitmap row
  61.         lsr.w    #3,d0            convert X1 to a byte offset
  62.         add.w    d0,d1            now d1=offset into bitplanes
  63.  
  64. ; compute the correct octant code for this line ( SUD,SUL,AUL ) and get the
  65. ; absolute value of max(deltaX, deltaY) into D2 for use as the line length.
  66.         tst.w    d2
  67.         bmi.s    40$            deltaX is negative
  68.  
  69. ; when deltaX is positive, use the following octant generation decisions
  70.         tst.w    d3        if deltaY is positive
  71.         bmi.s    20$
  72.         cmp.w    d3,d2            ...then if deltaX > deltaY...
  73.         blt.s    10$
  74.         moveq.l    #OCT4,d5        ...octant=4
  75.         bra.s    GotOctant
  76. 10$        moveq.l    #OCT0,d5        ...else octant=0...
  77.         exg    d2,d3            ...and switch the delta values
  78.         bra.s    GotOctant
  79.  
  80. 20$        neg.w    d3        else deltaY = -deltaY...
  81.         cmp.w    d3,d2            ...if deltaX > deltaY...
  82.         blt.s    30$
  83.         moveq.l    #OCT6,d5        ...octant=6
  84.         bra.s    GotOctant
  85. 30$        moveq.l    #OCT1,d5        ...else octant=1...
  86.         exg    d2,d3            ...and switch the delta values
  87.         bra.s    GotOctant
  88.  
  89. ; but when deltaX is negative, use these octant generation decisions instead
  90. 40$        neg.w    d2        deltaX = -deltaX
  91.         tst.w    d3        if deltaY is positive...
  92.         bmi.s    60$
  93.         cmp.w    d3,d2            ...then if deltaX > deltaY
  94.         blt.s    50$
  95.         moveq.l    #OCT5,d5        ...octant=5
  96.         bra.s    GotOctant
  97. 50$        moveq.l    #OCT2,d5        ...else octant=2...
  98.         exg    d2,d3            ...and switch the delta values
  99.         bra.s    GotOctant
  100.  
  101. 60$        neg.w    d3        else deltaY = -deltaY
  102.         cmp.w    d3,d2            if deltaX > deltaY...
  103.         blt.s    70$
  104.         moveq.l    #OCT7,d5        ...octant=7
  105.         bra.s    GotOctant
  106. 70$        moveq.l    #OCT3,d5        ...else octant = 6...
  107.         exg    d2,d3            ...and switch the delta values
  108.  
  109. ; gets to here with the octant code in D5 and ABS(MAX(deltaX,deltaY)) in D2
  110. GotOctant    addq.w    #1,d2            *** is this right ? ***
  111. 5$        add.w    d3,d3            D3 = 2Y
  112.         move.w    d3,d0            calculate initial error term
  113.         sub.w    d2,d0            D0=2Y-X
  114.         bpl.s    10$            no need to set SIGN
  115.         ori.w    #SIGN,d5        initial term is negative so...
  116. ;                        we start one line further up
  117.  
  118. ; this is a bit tricky, we need the start code in the top 4 bits of d5 and d4
  119. ; but they are currently in the low 4 bits of d4.  Instead of shifting them
  120. ; all the way up to position, we just rotate them around and or them in.
  121. 10$        ror.w    #4,d4            move start code to top bits
  122.         or.w    d4,d5            need shift in both halves...
  123. ;                        to shift line pattern too
  124.         ori.w    #USEA!USEC!USED,d4    move in codes for DMA channels
  125.  
  126. ; OK, let's start stuffing registers that won't change between successive blits
  127. ; so we can speed up the innner loop that draws a line in each bit plane. Make
  128. ; sure that the blitter is not busy from a previous line draw routine before
  129. ; we start storing to the registers.
  130.         move.w    #BBUSY,d6
  131. 20$        and.w    dmaconr(a3),d6        wait for the blitter to finish
  132.         bne.s    20$            still busy
  133.  
  134.         move.w    #SETBIT!BLTPRI,dmacon(a3)  give blit high priority
  135.         move.w    d3,bltbmod(a3)        bltbmod=2Y
  136.         move.w    d0,d3
  137.         sub.w    d2,d3            compute 2Y-2X
  138.         move.w    d3,bltamod(a3)        bltamod=2Y-2X
  139.         move.w    bm_BytesPerRow(a1),bltcmod(a3)
  140.         move.w    bm_BytesPerRow(a1),bltdmod(a3)
  141.         moveq.l    #-1,d3            first and last masks = $FFFF
  142.         move.l    d3,bltafwm(a3)        this stores to both
  143.         move.w    rp_LinePtrn(a0),bltbdat(a3) set up line pattern
  144.         asl.w    #6,d2            convert line length to bltsize
  145.         addq.w    #2,d2            width=2 for all line drawing
  146.         move.w    d5,bltcon1(a3)        set up bltcon1
  147.  
  148. ; stash things that need frequent reference during the plane drawing loop
  149.         move.b    rp_FgPen(a0),d5        get pen color
  150.         and.b    rp_Mask(a0),d5        and observe mask
  151.         clr.w    d3
  152.         move.b    bm_Depth(a1),d3        get a plane counter
  153.         lea.l    bm_Planes(a1),a1    point to array of plane ptrs
  154.         bra.s    LoopEntry
  155.  
  156. ; this is the loop that draws lines in each of the required bitplanes.
  157. ; Registers are set up as follows:-
  158. ;    D0 = 2Y-X
  159. ;    D1 = Offset in bitplane to first word of the line
  160. ;    D2 = BlitSize to start the blitter with
  161. ;    D3 = plane counter
  162. ;    D4 = bltcon0
  163. ;    D5 = pencolor
  164. ;    A1 = pointer to bitplane pointers
  165. ;    A3 = pointer to custom chips
  166. ; Notice that during the loop, the blitter can be busy drawing the last line
  167. ; segment while the CPU is setting up for the next load of stores.
  168. PlaneLoop    movea.l    (a1)+,a2        get next bitplane address
  169.         adda.w    d1,a2            start address of line
  170.         move.b    #$0a,d4            assume erasing (minterm = NAC)
  171.         lsr.w    #1,d5            shift next bit into carry
  172.         bcc.s    5$            it's 0 so erase this bit
  173.         move.b    #$ca,d4            NAC+AB we are drawing the line
  174.  
  175. 5$        move.w    #BBUSY,d6
  176. 10$        and.w    dmaconr(a3),d6        wait for the blitter to finish
  177.         bne.s    10$            still busy
  178.  
  179.         move.w    #$8000,bltadat(a3)    put in the line bit
  180.         move.l    a2,bltcpth(a3)        fill in line start address...
  181.         move.l    a2,bltdpth(a3)        ...of this line
  182.         move.w    d0,bltaptl(a3)        2Y-X, needs reloading each use
  183.         move.w    d4,bltcon0(a3)        store the minterm and stuff
  184.         move.w    d2,bltsize(a3)        ZOOOOM! start the line draw
  185. LoopEntry    dbra    d3,PlaneLoop        and do the next plane
  186.  
  187.         movem.l    (sp)+,d2-d6/a2-a3    restore regs
  188.         rts                all done
  189.  
  190. ;============================================================================
  191. ; Clear( rp )
  192. ;        a0
  193. ;
  194. ; Clears ALL bitmap memory in the given rastport.  Must call OwnBlitter()
  195. ; before calling this routine (or nasty things will happen fer sure).
  196. ; This routine assumes all bitplanes are contiguous in memory!!!!!!!!!!!!
  197. ;============================================================================
  198. Clear        movea.l    #_custom,a1        point to custom chips
  199.         movea.l    rp_BitMap(a0),a0    get the bitmap ptr
  200.         moveq.l    #0,d0
  201.         moveq.l    #0,d1
  202.         move.w    bm_Rows(a0),d0        calculate blitsize
  203.         move.b    bm_Depth(a0),d1
  204.         mulu.w    d1,d0            d0 = #lines to clear
  205.         lsl.l    #6,d0            move to correct bits
  206.         move.w    bm_BytesPerRow(a0),d1    get width in words
  207.         lsr.w    #1,d1
  208.         or.w    d1,d0            d0 = bltsize reg
  209.  
  210.         move.w    #BBUSY,d1
  211. 10$        and.w    dmaconr(a1),d1        wait for blitter to finish
  212.         bne.s    10$            the last operation
  213.  
  214.         move.w    #SETBIT!BLTPRI,dmacon(a1)    blitter nasty
  215.         clr.l    bltamod(a1)        bltamod & bltbmod = 0
  216.         clr.l    bltcmod(a1)        bltcmod & bltdmod = 0
  217.         clr.w    bltcon1(a1)        no shift or anything special
  218.         move.w    #$01f0,bltcon0(a1)    only using destination
  219.         move.l    bm_Planes(a0),bltdpth(a1)    where we are storing to
  220.         clr.w    bltadat(a1)        what we are storing (0's)
  221.         move.w    d0,bltsize(a1)        start the blit
  222.         rts                done
  223.  
  224.         END
  225.